import base64
import json
import logging
from typing import Dict, Any
from wechatpayv3 import WeChatPay, WeChatPayType
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_pem_public_key
# AES-256-GCM解密
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
import os


from config.dev import WECHATPAY_CONFIG

# 配置日志记录
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class WechatPayService:
    def __init__(self):
        # 读取商户证书私钥
        try:
            with open(WECHATPAY_CONFIG["private_key_path"]) as f:
                self.private_key = f.read()
        except FileNotFoundError:
            logging.error("商户证书私钥文件未找到")
            raise

        # 读取商户证书公钥
        try:
            with open(WECHATPAY_CONFIG["public_key_path"]) as f:
                self.public_key = f.read()
        except FileNotFoundError:
            logging.error("商户证书公钥文件未找到")
            raise

        # 初始化微信支付客户端（NATIVE支付类型）
        self.client = WeChatPay(
            wechatpay_type=WeChatPayType.NATIVE,
            appid=WECHATPAY_CONFIG["appid"],
            mchid=WECHATPAY_CONFIG["mch_id"],
            public_key_id=WECHATPAY_CONFIG["public_key_id"],
            private_key=self.private_key,
            public_key=self.public_key,
            cert_serial_no=WECHATPAY_CONFIG["cert_serial_no"],
            apiv3_key=WECHATPAY_CONFIG["apiv3_key"],
            notify_url=WECHATPAY_CONFIG["notify_url"],
            # cert_dir=WECHATPAY_CONFIG["cert_dir"]
        )

    def create_native_payment(self, out_trade_no: str, total_amount: int, description: str) -> Dict[str, Any]:
        """生成扫码支付调起参数（微信内调起支付面板）"""
        try:
            # 1. 调用微信扫码下单接口获取二维码链接
            # 构建订单参数
            order_params = {
                "description": description,
                "out_trade_no": out_trade_no,
                "amount": {"total": total_amount, "currency": "CNY"},
                "notify_url": WECHATPAY_CONFIG["notify_url"]
            }
            response = self.client.pay(**order_params)
            logger.info(f"微信扫码下单接口返回：{response}")
            # 微信扫码下单接口返回的是元组数据：(200, '{"code_url":"weixin://wxpay/bizpayurl?pr=0rAu5m6z1"}')
            # 正确处理元组并解析JSON
            if response[0] == 200:  # 检查HTTP状态码
                try:
                    data = json.loads(response[1])  # 解析JSON字符串为字典
                    code_url = data.get('code_url')  # 安全获取code_url
                    if code_url:
                        print(f"获取到的支付链接: {code_url}")
                        logger.info(f"微信扫码下单接口二维码链接：{code_url}")
                        return {
                            "code": 200,
                            "message": "扫码支付参数生成成功",
                            "data": {"code_url": code_url}
                        }
                    else:
                        logger.error("微信扫码下单接口二维码链接返回失败")
                        return {"code": 400, "message": "获取code_url失败"}
                except json.JSONDecodeError:
                    print("错误: 无法解析微信支付返回的JSON数据")
            else:
                print(f"错误: 微信支付接口返回非成功状态码 {response[0]}")
                data = json.loads(response[1])  # 解析JSON字符串为字典
                return {"code": response[0], "message": data["message"]}
        except Exception as e:
            logger.error(f"扫码支付参数生成失败：{e}")
            return {"code": 500, "message": str(e)}

    async def verify_notification(self, headers: Dict[str, str], request_data: bytes) -> Dict[str, Any]:
        """验证微信支付异步通知签名（修复版）"""
        try:
            # 1. 解析通知数据和头部信息
            notify_data = json.loads(request_data.decode("utf-8"))
            logger.info(f"微信通知原始数据：{notify_data}")
            
            # 2. 提取加密资源并解密
            resource = notify_data.get("resource")
            logger.info(f"加密资源：{resource}")
            if not resource:
                return {"success": False, "message": "缺少加密资源"}
            
            # 解密参数
            ciphertext = resource["ciphertext"]
            logger.info(f"加密内容：{ciphertext}")
            nonce = resource["nonce"]
            logger.info(f"随机数：{nonce}")
            associated_data = resource["associated_data"]
            logger.info(f"关联数据：{associated_data}")
            
            # 加载apiv3_key（注意：私钥不可明文存储，此处仅为演示）
            apiv3_key = WECHATPAY_CONFIG["apiv3_key"]  # 从配置获取apiv3_key
            logger.info(f"APIv3密钥：{apiv3_key}")
            
            
            key = apiv3_key.encode("utf-8")
            nonce_bytes = nonce.encode("utf-8")
            associated_data_bytes = associated_data.encode("utf-8")
            ciphertext_bytes = base64.b64decode(ciphertext)
            
            # 分离tag（最后16字节）
            tag = ciphertext_bytes[-16:]
            ciphertext_bytes = ciphertext_bytes[:-16]
            
            # 解密
            algorithm = algorithms.AES(key)
            mode = modes.GCM(nonce_bytes, tag)
            cipher = Cipher(algorithm, mode, backend=default_backend())
            decryptor = cipher.decryptor()
            decryptor.authenticate_additional_data(associated_data_bytes)
            plaintext = decryptor.update(ciphertext_bytes) + decryptor.finalize()
            decrypted_data = plaintext.decode("utf-8")
            logger.info(f"解密后的交易数据：{decrypted_data}")
            
            # 3. 提取签名相关参数
            signature = headers.get("wechatpay-signature")
            serial_no = headers.get("wechatpay-serial")
            timestamp = headers.get("wechatpay-timestamp")
            nonce_header = headers.get("wechatpay-nonce")  # 头部的nonce，区别于加密资源的nonce

            logger.info(f"签名：{signature}")
            logger.info(f"序列号：{serial_no}")
            logger.info(f"时间戳：{timestamp}")
            logger.info(f"随机数：{nonce_header}")

            if not all([signature, serial_no, timestamp, nonce_header]):
                return {"success": False, "message": "缺少签名参数"}
            
            # 4. 构建待验证的消息体（使用解密后的明文）
            message = f"{timestamp}\n{nonce_header}\n{decrypted_data}\n".encode("utf-8")
            
            logger.info(f"构建待验证的消息体：{message}")
            # 5. 加载微信支付平台公钥（注意：此处需替换为微信平台公钥，而非商户公钥）
            # 微信平台公钥可从微信支付商户平台下载，或通过API获取
            with open("utils/certs/wechat_certs/pub_key.pem", "rb") as f:
                platform_public_key = load_pem_public_key(f.read(), backend=default_backend())
            
            # 6. 验证签名
            signature_bytes = base64.b64decode(signature)
            platform_public_key.verify(
                signature_bytes,
                message,
                padding.PSS(
                    mgf=padding.MGF1(hashes.SHA256()),
                    salt_length=padding.PSS.MAX_LENGTH
                ),
                hashes.SHA256()
            )
            
            return {"success": True, "message": "签名验证成功", "data": json.loads(decrypted_data)}
        
        except Exception as e:
            logger.error(f"微信通知签名验证失败：{e}")
            return {"success": False, "message": str(e)}

    # async def verify_notification(self, headers: Dict[str, str], request_data: bytes) -> Dict[str, Any]:
    #     """验证微信支付异步通知签名"""
    #     try:
    #         # 1. 解析通知数据和头部信息
    #         notify_data = request_data.decode("utf-8")
    #         logger.info(f"微信通知内容：{notify_data}")
    #         logger.info(f"微信通知HTTP头信息：{headers}")
    #         signature = headers.get("wechatpay-signature")
    #         serial_no = headers.get("wechatpay-serial")
    #         timestamp = headers.get("wechatpay-timestamp")
    #         nonce = headers.get("wechatpay-nonce")

    #         logger.info(f"微信通知签名：{signature}")
    #         logger.info(f"序列号：{serial_no}")
    #         logger.info(f"时间戳：{timestamp}")
    #         logger.info(f"随机数：{nonce}")

    #         # 检查必要参数是否存在
    #         if not all([signature, serial_no, timestamp, nonce]):
    #             logger.error("微信通知缺少必要的签名参数")
    #             return {"success": False, "message": "缺少签名参数"}

    #         # 2. 构建待验证的消息体
    #         message = f"{timestamp}\n{nonce}\n{notify_data}\n".encode("utf-8")

    #         # 3. 加载微信支付平台公钥（已在__init__中读取）
    #         # 注意：公钥需是PEM格式（包含-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----）
    #         public_key = load_pem_public_key(self.public_key.encode("utf-8"), backend=default_backend())

    #         # 4. 解码签名（Base64）
    #         signature_bytes = base64.b64decode(signature)

    #         # 5. 使用RSA-SHA256验证签名
    #         public_key.verify(
    #             signature_bytes,
    #             message,
    #             padding.PSS(
    #                 mgf=padding.MGF1(hashes.SHA256()),
    #                 salt_length=padding.PSS.MAX_LENGTH
    #             ),
    #             hashes.SHA256()
    #         )

    #         # 验证通过
    #         return {"success": True, "message": "签名验证成功"}

    #     except Exception as e:
    #         logger.error(f"微信通知签名验证失败：{e}")
    #         return {"success": False, "message": str(e)}


    def query_order(self, out_trade_no: str) -> Dict[str, Any]:
        """查询微信订单状态"""
        try:
            result = self.client.query(out_trade_no=out_trade_no)
            logger.info(f"查询微信订单结果：{result}")
            # 微信支付接口返回的是元组数据：(200, '{"amount":{"payer_currency":"CNY","total":1},"appid":"wx2fd097b62e9525f4","mchid":"1567589221","out_trade_no":"ORDER7356612655433519104","promotion_detail":[],"scene_info":{"device_id":""},"trade_state":"NOTPAY","trade_state_desc":"订单未支付"}')
            if result[0] == 200:  # 检查HTTP状态码
                try:
                    data = json.loads(result[1])  # 解析JSON字符串为字典
                    return {
                        'code': 200,
                        'message': '查询订单成功',
                        'data': {
                            'trade_state': data.get('trade_state'),
                            'trade_state_desc': data.get('trade_state_desc'),
                        }
                    }
                except json.JSONDecodeError:
                    print("错误: 无法解析微信支付返回的JSON数据")
            return result
        except Exception as e:
            logger.error(f"查询微信订单失败：{e}")
            return {"code": 400, "message": str(e)}

    def close_order(self, out_trade_no: str) -> Dict[str, Any]:
        """根据订单编号关闭微信订单（用户主动取消和超时自动取消）"""
        try:
            result = self.client.close(out_trade_no=out_trade_no)
            logger.info(f"关闭微信订单结果：{result}")
            if result:
                return {"code": 200, "message": "订单已关闭"}
            else:
                return {"code": 500, "message": "关闭订单失败"}
        except Exception as e:
            logger.error(f"关闭微信订单失败：{e}")
            return {"code": 500, "message": str(e)}
